package com.moregold.mvvmlib.ext

import androidx.annotation.MainThread
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.rxLifeScope
import androidx.lifecycle.viewModelScope
import com.google.gson.JsonSyntaxException
import com.moregold.mvvmlib.base.BaseViewModel
import com.moregold.mvvmlib.entity.BaseResult
import com.moregold.mvvmlib.exception.AppException
import kotlinx.coroutines.launch
import java.lang.reflect.ParameterizedType
import java.net.ConnectException
import java.net.SocketException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.util.concurrent.TimeoutException

/**
 * 获取vm clazz
 */
@Suppress("UNCHECKED_CAST")
fun <VM> getVmClazz(obj: Any): VM {
    return (obj.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as VM
}

/**
 * 跟下面的方法类似,只是调用形式上有所区别
 * 这种vmResult要提前定义好
 * 下面vmResult: VmResult<T>.() -> Unit可以直接写在参数里面
 */
//@MainThread
//inline fun <T> VmLiveData<T>.vmObserver(owner: LifecycleOwner, vmResult: VmResult<T>) {
//    observe(owner) {
//        when (it) {
//            is VmState.Loading ->{
//                vmResult.onAppLoading()
//            }
//            is VmState.Success -> {
//                vmResult.onAppSuccess(it.data)
//                vmResult.onAppComplete()
//            }
//            is VmState.Error -> {
//                vmResult.onAppError(it.error)
//                vmResult.onAppComplete()
//            }
//        }
//    }
//}
//
///**
// * 重写所有回调方法
// * onAppLoading
// * onAppSuccess
// * onAppError
// * onAppComplete
// */
//@MainThread
//inline fun <T> VmLiveData<T>.vmObserver(owner: LifecycleOwner, vmResult: VmResult<T>.() -> Unit) {
//    val result = VmResult<T>();result.vmResult();observe(owner) {
//        when (it) {
//            is VmState.Loading ->{
//                result.onAppLoading()
//            }
//            is VmState.Success -> {
//                result.onAppSuccess(it.data);result.onAppComplete()
//            }
//            is VmState.Error -> {
//                result.onAppError(it.error);result.onAppComplete()
//            }
//        }
//    }
//}

/**
 *
 * 第一个参数继承自BaseActivity
 * 第二个参数 是否toast提示错误
 * 第三个参数 等待框
 * 第四个参数 成功回调
 */
@MainThread
inline fun <T> VmLiveData<T>.vmObserverDefault(
    activity: AppCompatActivity,
    tips: Boolean = true,
    crossinline onLoading: (() -> Unit) = {},
    crossinline onSuccess: ((T) -> Unit),
    crossinline onError: ((status :Int) -> Unit) = {}
) {
    observe(activity) {
        when (it) {
            is VmState.Loading ->{
                onLoading()
            }
            is VmState.Success -> {
                onSuccess(it.data)
            }
            is VmState.Error -> {
                onError(it.status)
                if(tips) activity.showToast(it.error.errorMsg)
            }
        }
    }
}

/**
 * 第一个参数继承自AppCompatActivity
 * 第二个参数 是否toast提示错误
 * 第三个参数 加载等待框
 * 第四个参数 成功回调
 * 第五个参数 不论成功还是失败都会回调,一般加了等待框就会需要这个回调
 */
@MainThread
inline fun <T> VmLiveData<T>.vmObserverDefault(
    activity: AppCompatActivity,
    tips: Boolean = true,
    crossinline onLoading: (() -> Unit) = {},
    crossinline onSuccess: ((T) -> Unit),
    crossinline onComplete: (() -> Unit) = {},
    crossinline onError: ((status :Int) -> Unit) = {}
) {
    observe(activity) {
        when (it) {
            is VmState.Loading ->{
                onLoading()
            }
            is VmState.Success -> {
                onSuccess(it.data)
                onComplete()
            }
            is VmState.Error -> {
                onError(it.status)
                if(tips) activity.showToast(it.error.errorMsg)
                onComplete()
            }
        }
    }
}


/**
 *
 * 第一个参数继承自BaseFragment
 * 第二个参数 是否toast提示错误
 * 第三个参数 等待框
 * 第四个参数 成功回调
 */
@MainThread
inline fun <T> VmLiveData<T>.vmObserverDefault(
    fragment: Fragment,
    tips: Boolean = true,
    crossinline onLoading: (() -> Unit) = {},
    crossinline onSuccess: ((T) -> Unit)
) {
    observe(fragment) {
        when (it) {
            is VmState.Loading ->{
                onLoading()
            }
            is VmState.Success -> {
                onSuccess(it.data)
            }
            is VmState.Error -> {
                if(tips) fragment.context!!.showToast(it.error.errorMsg)
            }
        }
    }
}

/**
 *
 * 第一个参数继承自BaseFragment
 * 第二个参数 是否toast提示错误
 * 第三个参数 等待框
 * 第四个参数 成功回调
 * 第五个参数 不论成功还是失败都会回调,一般加了等待框就会需要这个回调
 */
@MainThread
inline fun <T> VmLiveData<T>.vmObserverDefault(
    fragment: Fragment,
    tips: Boolean = true,
    crossinline onLoading: (() -> Unit) = {},
    crossinline onSuccess: ((T) -> Unit),
    crossinline onComplete: (() -> Unit) = {}
) {
    observe(fragment) {
        when (it) {
            is VmState.Loading ->{
                onLoading()
            }
            is VmState.Success -> {
                onSuccess(it.data)
                onComplete()
            }
            is VmState.Error -> {
                if(tips) fragment.context!!.showToast(it.error.errorMsg)
                onComplete()
            }
        }
    }
}

/**
 * BaseViewModel开启协程扩展
 */
fun <T> BaseViewModel.launchVmRequest(
    request: suspend () -> BaseResult<T>,
    viewState: VmLiveData<T>
) {
    rxLifeScope.launch {
        runCatching {
            viewState.value = VmState.Loading
            request()
        }.onSuccess {
            viewState.paresVmResult(it)
        }.onFailure {
            viewState.paresVmException(it)
        }
    }
}

fun <T> BaseViewModel.launchVmRequest2(
    request: suspend () -> BaseResult<T>,
    viewState: MutableLiveData<T>
) {
    rxLifeScope.launch {
        runCatching {
//            viewState.value = VmState.Loading
            request()
        }.onSuccess {
//            viewState.paresVmResult(it)
        }.onFailure {
//            viewState.paresVmException(it)
        }
    }
}

/**
 * BaseViewModel开启协程扩展
 * 为了符合项目纯json
 */
fun <T> BaseViewModel.launchVmRequestForJsonObject(
    request: suspend () -> T,
    viewState: VmLiveData<T>
) {
    rxLifeScope.launch {
        runCatching {
            viewState.value = VmState.Loading
            request()
        }.onSuccess {
            viewState.paresVmResultForJsonObject(it)
        }.onFailure {
            viewState.paresVmException(it)
        }
    }
}

/**
 * BaseViewModel开启协程扩展
 * 为了符合项目纯JsonArray
 */
fun <T> BaseViewModel.launchVmResultForJsonArray(
    request: suspend () -> T,
    viewState: VmLiveData<T>
) {
    rxLifeScope.launch {
        runCatching {
            viewState.value = VmState.Loading
            request()
        }.onSuccess {
            viewState.paresVmResultForJsonArray(it)
        }.onFailure {
            viewState.paresVmException(it)
        }
    }
}

/**
 * 网络错误提示
 */
fun Throwable?.parseErrorString(): String {
    return when (this) {
        is SocketException -> "网络错误"
        is ConnectException -> "网络错误"
        is UnknownHostException -> "无网络连接"
        is JsonSyntaxException -> "数据错误,json错误"
        is SocketTimeoutException -> "网络超时"
        is TimeoutException -> "网络超时"
        else -> "未知错误"
    }
}
